﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ZFBActivation.ThreadPool
{
	/// <summary>
	/// 线程池,用于运行相同工作的多线程处理
	/// </summary>
	/// <typeparam name="T">为继承DThread的类,并需要空构造函数,以便线程池创建</typeparam>
	public class DThreadPool<T> : IDisposable where T : DThread, new()
	{
		#region < 构造 >
		/// <summary>
		/// 构造函数
		/// </summary>
		/// <param name="threadCount">线程池中的线程数量</param>
		public DThreadPool(int threadCount) {
			_Sem = new SemaphoreSlim(0, int.MaxValue);
			_Threads = new List<T>(threadCount);
			_Queue = new Queue<T>();

			for (int i = 0; i < threadCount; i++) {
				//创建线程
				T t = new T();
				t.ThreadGiveBack += T_ThreadGiveBack;
				//加入队列
				_Queue.Enqueue(t);
				_Threads.Add(t);
				_Sem.Release();
			}
		}
		#endregion

		#region < 变量 >
		//信号量,对没有对象可用时,将等待
		private SemaphoreSlim _Sem;
		//线程列表
		private List<T> _Threads;
		//线程队列
		private Queue<T> _Queue;
		#endregion

		#region < 方法 >
		//归还线程到线程池
		private void T_ThreadGiveBack(object sender, EventArgs e) {
			lock (this) {
				if(_Queue != null) {
					_Queue.Enqueue((T)sender);
				}
			}
			if(_Sem != null) {
				_Sem.Release();
			}

		}

		/// <summary>
		/// 获取一个线程进行工作
		/// </summary>
		/// <returns>T</returns>
		public T Get() {
			_Sem.Wait();

			lock (this) {
				if(_Queue != null) {
					return _Queue.Dequeue();
				}
				return default(T);
			}
		}

		/// <summary>
		/// 可用线程
		/// </summary>
		public int GetT {
			get { return _Queue.Count; }
		}

		#endregion

		#region < IDisposable 成员 >
		/// <summary>
		/// 释放资源
		/// </summary>
		/// <param name="disposing">为true则释放托管资源和非托管资源,为false则仅释放非托管资源.</param>
		protected virtual void Dispose(bool disposing) {
			if (_Sem != null) {
				_Sem.Dispose();
				_Sem = null;
			}

			if (_Threads != null) {
				_Threads.ForEach(item => item.Dispose());
				_Threads.Clear();
				_Threads = null;
			}

			if (_Queue != null) {
				_Queue.Clear();
				_Queue = null;
			}
		}

		/// <summary>
		/// 释放资源
		/// </summary>
		public void Dispose() {
			Dispose(true);
			GC.SuppressFinalize(this);
		}
		#endregion
	}
}
